home *** CD-ROM | disk | FTP | other *** search
- /* XGScrollView.cpp
- *
- * This handles the scrolling view; this is a view which sets
- * up two scrollbars in the sides and manages scrolling a center view
- */
-
- /* YAAF - Yet another application framework
- * Copyright (C) 1997 William Edward Woody and In Phase Consulting
- *
- * This library is free software; you can redistribute it
- * and/or modify it under the terms of the GNU Library
- * General Public License as published by the Free Software
- * Foundation; either version 2 of the License, or any
- * later version.
- *
- * This library is distributed in the hope that it will be
- * useful, but WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABIILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU Library General Public License for
- * more details.
- *
- * You should have received a copy of the GNU Library General
- * Public License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * To contact the author, either e-mail me at
- * woody@alumni.caltech.edu, or write to us at
- *
- * William Edward Woody
- * In Phase Consulting
- * 1545 Ard Eevin Avenue
- * Glendale, CA 91202
- */
-
- #include <XError.h>
- #include <XStdScrollView.h>
-
- /************************************************************************/
- /* */
- /* Set/Clear Class Object */
- /* */
- /************************************************************************/
-
- /* XGIClear
- *
- * This class object clears the specified boolean value when
- * it is created, and sets it when it is exited. This is used
- * whenever I want to clear the fBounce flag temporarly; it
- * guarentees that the flag is set back, even when an error is thrown.
- */
-
- class XGIClear {
- public:
- XGIClear(bool &a) { fA = &a; a = false; }
- ~XGIClear() { *fA = true; }
- private:
- bool *fA;
- };
-
- /************************************************************************/
- /* */
- /* Construction/Destruction */
- /* */
- /************************************************************************/
-
- /* XGScrollView::XGScrollView
- *
- * Construct this thing
- */
-
- XGScrollView::XGScrollView(XGView *parent, XGArgStream &stream) :
- XGView(parent,stream)
- {
- bool h;
- bool v;
- bool c;
- short s;
-
- h = stream.GetBoolean();
- v = stream.GetBoolean();
- c = stream.GetBoolean();
- s = stream.GetInteger();
-
- Init(h,v,c,s);
- }
-
- XGScrollView::XGScrollView(XGView *parent, XGSScrollViewInitRecord &i) :
- XGView(parent,i.v)
- {
- Init(i.hscroll,i.vscroll,i.corner,i.viewID);
- }
-
- /* XGScrollView::~XGScrollView
- *
- * Destruction. Do nothing, as the view deconstructor will
- * automatically fry my two scrollbars for me
- */
-
- XGScrollView::~XGScrollView()
- {
- fHScroll = NULL;
- fVScroll = NULL;
- }
-
- /************************************************************************/
- /* */
- /* Display management */
- /* */
- /************************************************************************/
-
- /* XGScrollView::DoDrawView
- *
- * Handle drawing the corner if it's called for. On the Macintosh
- * I simply erase the corner to the background color--on Windows, to
- * a light gray.
- */
-
- void XGScrollView::DoDrawView(Rect)
- {
- Rect r;
-
- if (fCorner) {
- XGDraw draw(this);
-
- r = CalcCorner();
-
- #if OPT_MACOS == 1
- ::EraseRect(&r);
- #endif
-
- #if OPT_WINOS == 1
- ::FillRect(draw.GetDC(),&r,GetStockObject(LTGRAY_BRUSH));
- #endif
- }
- }
-
- /* XGScrollView::DoSizeView
- *
- * Resize this view. This routine resizes everything using
- * AutoLocate, but inside the scroll rectangle. The exceptions are
- * the two scrollbars
- */
-
- void XGScrollView::DoSizeView()
- {
- XGView *view;
-
- for (view = GetChild(); view != NULL; view = view->GetSibling()) {
- if (view == fHScroll) view->SetLocation(CalcHScroll());
- else if (view == fVScroll) view->SetLocation(CalcVScroll());
- else view->AutoLocate(CalcScroll());
- }
- }
-
- /************************************************************************/
- /* */
- /* Scroll Management */
- /* */
- /************************************************************************/
-
- /* XGScrollView::GetScrollValue
- *
- * Get the current scroll view location
- */
-
- void XGScrollView::GetScrollValue(short *x, short *y)
- {
- if (fHScroll) *x = fHScroll->GetValue();
- else *x = 0;
- if (fVScroll) *y = fVScroll->GetValue();
- else *y = 0;
- }
-
- /* XGScrollView::SetScrollValue
- *
- * Set the scroll bar location to the new value. This is done
- * in this complex way in order to guarentee that I scroll both
- * axis at the same time.
- */
-
- void XGScrollView::SetScrollValue(short x, short y)
- {
- XGIClear clear(fBounce); // Clear bounce flag for me
- short ox,oy;
-
- /*
- * Get the old value
- */
-
- GetScrollValue(&ox,&oy);
-
- /*
- * Set and get the new value
- */
-
- if (fHScroll) fHScroll->SetValue(x);
- else if (x != 0) {
- XPostError("Horizontal scroll bar not present");
- }
- if (fVScroll) fVScroll->SetValue(y);
- else if (y != 0) {
- XPostError("Vertical scroll bar not present");
- }
-
- GetScrollValue(&x,&y);
-
- /*
- * Scroll the view if needed
- */
-
- if ((x != ox) && (y != oy)) {
- UpdateChildView();
- ScrollChildView(ox,oy);
- }
- }
-
- /* XGScrollView::GetScrollMax
- *
- * Get the maximum value to scroll
- */
-
- void XGScrollView::GetScrollMax(short *x, short *y)
- {
- if (fHScroll) *x = fHScroll->GetMaxValue();
- else *x = 0;
- if (fVScroll) *y = fVScroll->GetMaxValue();
- else *y = 0;
- }
-
- /* XGScrollView::SetScrollMax
- *
- * Set the scroll bar location to the new value. This is done
- * in this complex way in order to guarentee that I scroll both
- * axis at the same time.
- */
-
- void XGScrollView::SetScrollMax(short x, short y)
- {
- XGIClear clear(fBounce); // Clear bounce flag for me
- short ox,oy;
-
- /*
- * Get the old value
- */
-
- GetScrollValue(&ox,&oy);
-
- /*
- * Set and get the new value
- */
-
- if (fHScroll) fHScroll->SetMaxValue(x);
- else if (x != 0) {
- XPostError("Horizontal scroll bar not present");
- }
- if (fVScroll) fVScroll->SetMaxValue(y);
- else if (y != 0) {
- XPostError("Vertical scroll bar not present");
- }
-
- GetScrollValue(&x,&y);
-
- /*
- * Scroll the view if needed
- */
-
- if ((x != ox) && (y != oy)) {
- UpdateChildView();
- ScrollChildView(ox,oy);
- }
- }
-
- /* XGScrollView::GetScrollPage
- *
- * Get the page size amount for this thing
- */
-
- void XGScrollView::GetScrollPage(short *x, short *y)
- {
- if (fHScroll) *x = fHScroll->GetPageValue();
- else *x = 0;
- if (fVScroll) *y = fVScroll->GetPageValue();
- else *y = 0;
- }
-
- /* XGScrollView::SetScrollPage
- *
- * Set the page size for this thing
- */
-
- void XGScrollView::SetScrollPage(short x, short y)
- {
- if (fHScroll) fHScroll->SetPageValue(x);
- else if (x != 0) {
- XPostError("Horizontal scroll bar not present");
- }
- if (fVScroll) fVScroll->SetPageValue(y);
- else if (y != 0) {
- XPostError("Vertical scroll bar not present");
- }
- }
-
-
- /************************************************************************/
- /* */
- /* Message dispatch */
- /* */
- /************************************************************************/
-
- /* XGScrollView::ReceiveDispatch
- *
- * This sends the scrollbar control messages to my children
- * views.
- */
-
- long XGScrollView::ReceiveDispatch(long msg, long arg, void *parg)
- {
- XGSScrollEvent *e;
-
- if (fBounce) switch (msg) {
- case KEventPreScroll:
- /*
- * The scrollbar is about to scroll. Force update of the
- * bits in my child view
- */
-
- UpdateChildView();
- return 0;
- case KEventScroll:
- /*
- * The scrollbar is scrolling. Scroll the bits
- */
-
- e = (XGSScrollEvent *)parg;
- if (e->scroll == fHScroll) ScrollChildView(e->oldvalue,0);
- else if (e->scroll == fVScroll) ScrollChildView(0,e->oldvalue);
- else return XGView::ReceiveDispatch(msg,arg,parg);
- return 0;
- default:
- break;
- }
-
- return XGView::ReceiveDispatch(msg,arg,parg);
- }
-
- /************************************************************************/
- /* */
- /* Initialization support */
- /* */
- /************************************************************************/
-
- /* XGScrollView::Init
- *
- * Common initilization
- */
-
- void XGScrollView::Init(bool h, bool v, bool c, short s)
- {
- XGSScrollInitRecord si;
- Rect r;
-
- /*
- * Bit sanity check
- */
-
- if (!h && !v) {
- throw XPostError("Must have at least one scrollbar in a scroll view");
- }
- if (h && v) c = true; /* Override corner bit */
-
- /*
- * Initialize random fields
- */
-
- fChildID = s;
- fCorner = c;
- fDelta = 12; /* Random stupid value */
- fHScroll = NULL;
- fVScroll = NULL;
- fBounce = true;
-
- /*
- * Time to initialize my scrollbars
- */
-
- if (h) {
- r = CalcHScroll();
-
- si.v.fViewType = 'scrl'; /* Scroll bar */
- si.v.fViewID = -1; /* Ignored ID */
- si.v.fRefNum = 0; /* RefCon value ignored */
-
- si.v.fLockLeft = false; /* Ignored values */
- si.v.fLockLeft = false;
- si.v.fLockLeft = false;
- si.v.fLockLeft = false;
-
- si.v.fAutoLeft = r.left; /* Where do I go? */
- si.v.fAutoRight = r.right;
- si.v.fAutoTop = r.top;
- si.v.fAutoBottom = r.bottom;
-
- si.v.fVisible = true;
- si.v.fEnabled = true;
- si.v.fTabStop = false;
-
- si.page = 0; /* Random stupid value */
- si.min = 0;
- si.max = 0;
- si.val = 0;
-
- fHScroll = new XGStdScroll(this,si);
- }
-
- if (v) {
- r = CalcVScroll();
-
- si.v.fViewType = 'scrl'; /* Scroll bar */
- si.v.fViewID = -1; /* Ignored ID */
- si.v.fRefNum = 0; /* RefCon value ignored */
-
- si.v.fLockLeft = false; /* Ignored values */
- si.v.fLockLeft = false;
- si.v.fLockLeft = false;
- si.v.fLockLeft = false;
-
- si.v.fAutoLeft = r.left; /* Where do I go? */
- si.v.fAutoRight = r.right;
- si.v.fAutoTop = r.top;
- si.v.fAutoBottom = r.bottom;
-
- si.v.fVisible = true;
- si.v.fEnabled = true;
- si.v.fTabStop = false;
-
- si.page = 0; /* Random stupid value */
- si.min = 0;
- si.max = 0;
- si.val = 0;
-
- fVScroll = new XGStdScroll(this,si);
- }
- }
-
-
- /************************************************************************/
- /* */
- /* Dimension calculation */
- /* */
- /************************************************************************/
-
- /* XGScrollView::CalcHScroll
- *
- * Calculate the location of the horizontal scroll bar
- */
-
- Rect XGScrollView::CalcHScroll()
- {
- Rect r;
-
- r = GetContentRect();
-
- #if OPT_MACOS == 1
- r.bottom++;
- r.top = r.bottom - 16;
- r.left--;
- if (fCorner) {
- r.right -= 14;
- } else {
- r.right++;
- }
- #endif
-
- #if OPT_WINOS == 1
- r.top = r.bottom - ::GetSystemMetrics(SM_CYHSCROLL);
- if (fCorner) {
- r.right -= ::GetSystemMetrics(SM_CXVSCROLL);
- }
- #endif
-
- return r;
- }
-
- /* XGScrollView::CalcVScroll
- *
- * Calculate the vertical scroll bar location
- */
-
- Rect XGScrollView::CalcVScroll()
- {
- Rect r;
-
- r = GetContentRect();
-
- #if OPT_MACOS == 1
- r.right++;
- r.left = r.right - 16;
- r.top--;
- if (fCorner) {
- r.bottom -= 14;
- } else {
- r.bottom++;
- }
- #endif
-
- #if OPT_WINOS == 1
- r.left = r.right - ::GetSystemMetrics(SM_CYHSCROLL);
- if (fCorner) {
- r.bottom -= ::GetSystemMetrics(SM_CXVSCROLL);
- }
- #endif
-
- return r;
- }
-
- /* XGScrollView::CalcCorner
- *
- * Calculate the corner size
- */
-
- Rect XGScrollView::CalcCorner()
- {
- Rect r;
-
- r = GetContentRect();
-
- #if OPT_MACOS == 1
- r.top = r.bottom - 14;
- r.left = r.right - 14;
- #endif
-
- #if OPT_WINOS == 1
- r.top = r.bottom - ::GetSystemMetrics(SM_CYHSCROLL);
- r.left = r.right - ::GetSystemMetrics(SM_CYHSCROLL);
- #endif
-
- return r;
- }
-
- /* XGScrollView::CalcScroll
- *
- * Calculate the scrollbar area
- */
-
- Rect XGScrollView::CalcScroll()
- {
- Rect r;
-
- r = GetContentRect();
-
- #if OPT_MACOS == 1
- if (fHScroll) r.bottom = r.bottom - 15;
- if (fVScroll) r.right = r.right - 15;
- #endif
-
- #if OPT_WINOS == 1
- if (fHScroll) r.bottom = r.bottom - ::GetSystemMetrics(SM_CYHSCROLL);
- if (fVScroll) r.right = r.right - ::GetSystemMetrics(SM_CYHSCROLL);
- #endif
-
- return r;
- }
-
- /************************************************************************/
- /* */
- /* Child view support */
- /* */
- /************************************************************************/
-
- /* XGScrollView::InvalChildView
- *
- * Invalidate child view
- */
-
- void XGScrollView::InvalChildView()
- {
- XGView *v;
-
- v = FindViewByID(fChildID);
- if (v) v->InvalView();
- }
-
- /* XGScrollView::UpdateChildView
- *
- * Update child view
- */
-
- void XGScrollView::UpdateChildView()
- {
- XGView *v;
-
- v = FindViewByID(fChildID);
- if (v) v->UpdateView();
- }
-
- /* XGScrollView::ScrollChildView
- *
- * Scroll the child view
- */
-
- void XGScrollView::ScrollChildView(short ox, short oy)
- {
- short nx,ny;
- long dx,dy;
- XGView *v;
-
- v = FindViewByID(fChildID);
- if (!v) return;
-
- /* Calculate scroll amount */
- GetScrollValue(&nx,&ny);
- dx = (long)(ox - nx) * fDelta;
- dy = (long)(oy - ny) * fDelta;
- v->Scroll(dx,dy);
- v->UpdateView();
- }
-